<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>caffe的Makefile编译体系 | linqinghuang</title>
  <meta name="keywords" content="">
  <meta name="description" content="caffe的Makefile编译体系 | linqinghuang">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="能力定位perf工具常用于性能优化">
<meta name="keywords" content="性能优化">
<meta property="og:type" content="article">
<meta property="og:title" content="perf使用">
<meta property="og:url" content="http:&#x2F;&#x2F;yoursite.com&#x2F;2020&#x2F;03&#x2F;11&#x2F;%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96&#x2F;perf%E4%BD%BF%E7%94%A8&#x2F;index.html">
<meta property="og:site_name" content="linqinghuang">
<meta property="og:description" content="能力定位perf工具常用于性能优化">
<meta property="og:locale" content="en">
<meta property="og:updated_time" content="2020-03-10T16:08:46.246Z">
<meta name="twitter:card" content="summary">


<link rel="icon" href="/img/lin.png">

<link href="/css/style.css?v=1.0.1" rel="stylesheet">

<link href="/css/hl_theme/sublime.css?v=1.0.1" rel="stylesheet">

<link href="//cdn.bootcss.com/animate.css/3.5.2/animate.min.css" rel="stylesheet">
<link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="/js/jquery.autocomplete.min.js?v=1.0.1" ></script>

<script src="//cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>
<script>
    hljs.initHighlightingOnLoad();
</script>

<script src="//cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js"></script>



<script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js" ></script>

<script src="/js/iconfont.js?v=1.0.1" ></script>

</head>
<div style="display: none">
  <input class="theme_disqus_on" value="false">
  <input class="theme_preload_comment" value="false">
  <input class="theme_blog_path" value="">
</div>

<body>
<aside class="nav">
    <div class="nav-left">
        <a href="/" class="avatar_target">
    <img class="avatar" src="/img/lin.png" />
</a>
<div class="author">
    <span>linqinghuang</span>
</div>

<div class="icon">
    
</div>




<ul>
    <li><div class="all active">全部文章<small>(11)</small></div></li>
    
        
            
            <li><div data-rel="性能优化">性能优化<small>(1)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="程序编译调试">程序编译调试<small>(6)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="目标检测">目标检测<small>(1)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="计算机视觉"><i class="fold iconfont icon-right"></i>计算机视觉<small>(2)</small></div>
                
                    <ul class="sub hide">
                        
                        <li><div data-rel="精度测量及优化">精度测量及优化<small>(1)</small></div>
                            
                        </li>
                            
                    </ul>
                
            </li>
            
        
    
        
            
        
    
</ul>
<div class="left-bottom">
    <div class="menus">
    
    
    </div>
    <div><a class="about  site_url"  href="/about">关于</a></div>
</div>
<input type="hidden" id="yelog_site_posts_number" value="11">

<div style="display: none">
    <span id="busuanzi_value_site_uv"></span>
    <span id="busuanzi_value_site_pv"></span>
</div>

    </div>
    <div class="nav-right">
        <div class="friends-area">
    <div class="friends-title">
        友情链接
        <i class="back-title-list"></i>
    </div>
    <div class="friends-content">
        <ul>
            
        </ul>
    </div>
</div>
        <div class="title-list">
    <form onkeydown="if(event.keyCode==13){return false;}">
        <input class="search" type="text" placeholder="Search..." autocomplete="off"id="local-search-input" >
        <i class="cross"></i>
        <span>
            <label for="tagswitch">Tags:</label>
            <input id="tagswitch" type="checkbox" style="display: none" />
            <i id="tagsWitchIcon"></i>
        </span>
    </form>
    <div class="tags-list">
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color5">性能优化</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color5">科学上网</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color1">v2ray</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color2">shadowsocks</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color5">目标检测</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color2">object detection</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color1">computer vision</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color4">gdb</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color3">调试</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color4">gcc</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color3">编译</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color4">g++</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color5">精度测量</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" target="_blank" rel="noopener" class="color4">mAP</a>
    </li>
    
    <div class="clearfix"></div>
</div>

    
    <nav id="title-list-nav">
        
        <a  class="性能优化 "
           href="/2020/03/11/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/perf%E4%BD%BF%E7%94%A8/"
           data-tag="性能优化"
           data-author="" >
            <span class="post-title" title="perf使用">perf使用</span>
            <span class="post-date" title="2020-03-11 00:08:00">2020/03/11</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2019/12/10/%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/"
           data-tag="科学上网,v2ray,shadowsocks"
           data-author="" >
            <span class="post-title" title="科学上网">科学上网</span>
            <span class="post-date" title="2019-12-10 00:11:00">2019/12/10</span>
        </a>
        
        <a  class="目标检测 "
           href="/2020/03/10/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/%E5%B8%B8%E8%A7%81%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E7%AE%97%E6%B3%95/"
           data-tag="目标检测"
           data-author="" >
            <span class="post-title" title="常见目标检测算法">常见目标检测算法</span>
            <span class="post-date" title="2020-03-10 00:13:00">2020/03/10</span>
        </a>
        
        <a  class=""
           href="/2020/02/04/caffe/caffe%E7%9A%84%E7%BC%96%E8%AF%91%E4%BD%93%E7%B3%BB/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="caffe的Makefile编译体系">caffe的Makefile编译体系</span>
            <span class="post-date" title="2020-02-04 07:51:05">2020/02/04</span>
        </a>
        
        <a  class="计算机视觉 "
           href="/2020/03/28/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E5%8F%91%E5%B1%95%E5%8E%86%E5%8F%B2%E5%9B%9E%E9%A1%BE/"
           data-tag="object detection,computer vision"
           data-author="" >
            <span class="post-title" title="计算机视觉发展历史回顾">计算机视觉发展历史回顾</span>
            <span class="post-date" title="2020-03-28 22:09:00">2020/03/28</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2020/03/14/%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%B0%83%E8%AF%95/gdb%E4%BD%BF%E7%94%A8/gdb%E8%BF%9B%E9%98%B6/"
           data-tag="gdb,调试"
           data-author="" >
            <span class="post-title" title="gdb进阶">gdb进阶</span>
            <span class="post-date" title="2020-03-14 23:41:00">2020/03/14</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2020/03/10/%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%B0%83%E8%AF%95/gdb%E4%BD%BF%E7%94%A8/%E4%BD%8D%E7%BD%AE%E6%97%A0%E5%85%B3%E4%BB%A3%E7%A0%81PIC/"
           data-tag="gcc,编译"
           data-author="" >
            <span class="post-title" title="位置无关代码PIC">位置无关代码PIC</span>
            <span class="post-date" title="2020-03-10 23:41:00">2020/03/10</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2020/03/10/%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%B0%83%E8%AF%95/gdb%E4%BD%BF%E7%94%A8/gdb%E5%9F%BA%E7%A1%80/"
           data-tag="gdb,调试"
           data-author="" >
            <span class="post-title" title="gcc和gdb基础">gcc和gdb基础</span>
            <span class="post-date" title="2020-03-10 23:41:00">2020/03/10</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2020/03/10/%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%B0%83%E8%AF%95/gdb%E4%BD%BF%E7%94%A8/g++%E7%BC%96%E8%AF%91%E5%B8%B8%E8%A7%81%E7%9A%84%E7%BC%96%E8%AF%91%E5%8F%82%E6%95%B0/"
           data-tag="编译,g++"
           data-author="" >
            <span class="post-title" title="g++常见的编译参数">g++常见的编译参数</span>
            <span class="post-date" title="2020-03-10 23:41:00">2020/03/10</span>
        </a>
        
        <a  class="程序编译调试 "
           href="/2020/03/14/%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%B0%83%E8%AF%95/gdb%E4%BD%BF%E7%94%A8/gdb%E9%AB%98%E9%98%B6/"
           data-tag="gdb,调试"
           data-author="" >
            <span class="post-title" title="gdb高阶">gdb高阶</span>
            <span class="post-date" title="2020-03-14 23:41:00">2020/03/14</span>
        </a>
        
        <a  class="计算机视觉 精度测量及优化 "
           href="/2020/03/10/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/%E7%B2%BE%E5%BA%A6%E6%B5%8B%E9%87%8F%E5%8F%8A%E4%BC%98%E5%8C%96/mAP/"
           data-tag="目标检测,精度测量,mAP"
           data-author="" >
            <span class="post-title" title="mAP">mAP</span>
            <span class="post-date" title="2020-03-10 00:13:00">2020/03/10</span>
        </a>
        
    </nav>
</div>
    </div>
    <div class="hide-list">
        <div class="semicircle">
            <div class="brackets first"><</div>
            <div class="brackets">&gt;</div>
        </div>
    </div>
</aside>
<div class="post">
    <div class="pjax">
        <article id="post-caffe/caffe的编译体系" class="article article-type-post" itemscope itemprop="blogPost">
    
        <h1 class="article-title">caffe的Makefile编译体系</h1>
    
    <div class="article-meta">
        
        
        
        
    </div>
    <div class="article-meta">
        
        创建时间:<time class="date" title='更新时间: 2020-02-05 08:24:24'>2020-02-04 07:51</time>
        
    </div>
    <div class="article-meta">
        
        
        <span id="busuanzi_container_page_pv">
            阅读:<span id="busuanzi_value_page_pv">
                <span class="count-comment">
                    <span class="spinner">
                      <div class="cube1"></div>
                      <div class="cube2"></div>
                    </span>
                </span>
            </span>
        </span>
        
        
        <span class="top-comment" title="跳转至评论区">
            <a href="#comments">
                评论:<span class="count-comment">
                    <span class="spinner">
                      <div class="cube1"></div>
                      <div class="cube2"></div>
                    </span>
                </span>
            </a>
        </span>
        
    </div>
    
    <div class="toc-ref">
    
        <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#caffe框架的Makefile编译体系"><span class="toc-text">caffe框架的Makefile编译体系</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Makefile文件全注释"><span class="toc-text">Makefile文件全注释</span></a></li></ol>
    
<style>
    .left-col .switch-btn,
    .left-col .switch-area {
        display: none;
    }
    .toc-level-3 i,
    .toc-level-3 ol {
        display: none !important;
    }
</style>
</div>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h3 id="caffe框架的Makefile编译体系"><a href="#caffe框架的Makefile编译体系" class="headerlink" title="caffe框架的Makefile编译体系"></a>caffe框架的Makefile编译体系</h3><p>在caffe框架源码的根目录下，有两份主要的编译文件。Makefile和Makefile.config.example。显然，使用makefile对<br>caffe的源代码进行编译之前，需要先拷贝Makefile.config.example，并命名为Makefile.config，用于作为Makefile的<br>配置文件。</p>
<p>Makefile.config主要用于设置一些依赖库以及一些头文件的路径等。</p>
<p>在Makefile的第二行中包含了该配置文件：</p>
<p><code>CONFIG_FILE := Makefile.config</code></p>
<h3 id="Makefile文件全注释"><a href="#Makefile文件全注释" class="headerlink" title="Makefile文件全注释"></a>Makefile文件全注释</h3><pre><code class="Makefile">PROJECT := caffe #设置变量, 使用 ：=而不是 =，可以避免递归赋值

CONFIG_FILE := Makefile.config #设置变量

#一段shell命令，用于检查配置文件是否存在
# Explicitly check for the config file, otherwise make -k will proceed anyway.
ifeq ($(wildcard $(CONFIG_FILE)),)#wildcard用于查找当前路径下的文件，找到了就返回0
$(error $(CONFIG_FILE) not found. See $(CONFIG_FILE).example.)
endif
include $(CONFIG_FILE) #使用include的方法添加，相当于Makefile.config其实也是一个Makefile文件

#设置build路径还有release路径

BUILD_DIR_LINK := $(BUILD_DIR)
ifeq ($(RELEASE_BUILD_DIR),)
    RELEASE_BUILD_DIR := .$(BUILD_DIR)_release
endif
ifeq ($(DEBUG_BUILD_DIR),)
    DEBUG_BUILD_DIR := .$(BUILD_DIR)_debug
endif

DEBUG ?= 0
ifeq ($(DEBUG), 1)
    BUILD_DIR := $(DEBUG_BUILD_DIR)
    OTHER_BUILD_DIR := $(RELEASE_BUILD_DIR)
else
    BUILD_DIR := $(RELEASE_BUILD_DIR)
    OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR)
endif

#添加所有包含源代码的路径，使用shell的find命令，查找所有的cpp还有proto文件
# All of the directories containing code.
SRC_DIRS := $(shell find * -type d -exec bash -c &quot;find {} -maxdepth 1 \
    \( -name &#39;*.cpp&#39; -o -name &#39;*.proto&#39; \) | grep -q .&quot; \; -print)

# The target shared library name
LIBRARY_NAME := $(PROJECT)
LIB_BUILD_DIR := $(BUILD_DIR)/lib
STATIC_NAME := $(LIB_BUILD_DIR)/lib$(LIBRARY_NAME).a
DYNAMIC_VERSION_MAJOR         := 1
DYNAMIC_VERSION_MINOR         := 0
DYNAMIC_VERSION_REVISION     := 0
DYNAMIC_NAME_SHORT := lib$(LIBRARY_NAME).so
#DYNAMIC_SONAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR)
DYNAMIC_VERSIONED_NAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION)
DYNAMIC_NAME := $(LIB_BUILD_DIR)/$(DYNAMIC_VERSIONED_NAME_SHORT)
COMMON_FLAGS += -DCAFFE_VERSION=$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION)

##############################
# Get all source files，获取所有的源文件
##############################
# CXX_SRCS are the source files excluding the test ones.
CXX_SRCS := $(shell find src/$(PROJECT) ! -name &quot;test_*.cpp&quot; -name &quot;*.cpp&quot;)#c++文件
# CU_SRCS are the cuda source files
CU_SRCS := $(shell find src/$(PROJECT) ! -name &quot;test_*.cu&quot; -name &quot;*.cu&quot;)#cu文件
# TEST_SRCS are the test source files
TEST_MAIN_SRC := src/$(PROJECT)/test/test_caffe_main.cpp#测试代码主文件
TEST_SRCS := $(shell find src/$(PROJECT) -name &quot;test_*.cpp&quot;)
TEST_SRCS := $(filter-out $(TEST_MAIN_SRC), $(TEST_SRCS))
TEST_CU_SRCS := $(shell find src/$(PROJECT) -name &quot;test_*.cu&quot;)
GTEST_SRC := src/gtest/gtest-all.cpp#gtest文件
# TOOL_SRCS are the source files for the tool binaries
TOOL_SRCS := $(shell find tools -name &quot;*.cpp&quot;)#工具源码文件
# EXAMPLE_SRCS are the source files for the example binaries
EXAMPLE_SRCS := $(shell find examples -name &quot;*.cpp&quot;)#例子源码文件
# BUILD_INCLUDE_DIR contains any generated header files we want to include.
BUILD_INCLUDE_DIR := $(BUILD_DIR)/src
# PROTO_SRCS are the protocol buffer definitions
PROTO_SRC_DIR := src/$(PROJECT)/proto#谷歌的proto协议文件路径
PROTO_SRCS := $(wildcard $(PROTO_SRC_DIR)/*.proto)
# PROTO_BUILD_DIR will contain the .cc and obj files generated from
# PROTO_SRCS; PROTO_BUILD_INCLUDE_DIR will contain the .h header files
PROTO_BUILD_DIR := $(BUILD_DIR)/$(PROTO_SRC_DIR)
PROTO_BUILD_INCLUDE_DIR := $(BUILD_INCLUDE_DIR)/$(PROJECT)/proto
# NONGEN_CXX_SRCS includes all source/header files except those generated
# automatically (e.g., by proto).
NONGEN_CXX_SRCS := $(shell find \
    src/$(PROJECT) \
    include/$(PROJECT) \
    python/$(PROJECT) \
    matlab/+$(PROJECT)/private \
    examples \
    tools \
    -name &quot;*.cpp&quot; -or -name &quot;*.hpp&quot; -or -name &quot;*.cu&quot; -or -name &quot;*.cuh&quot;)
LINT_SCRIPT := scripts/cpp_lint.py
LINT_OUTPUT_DIR := $(BUILD_DIR)/.lint
LINT_EXT := lint.txt
LINT_OUTPUTS := $(addsuffix .$(LINT_EXT), $(addprefix $(LINT_OUTPUT_DIR)/, $(NONGEN_CXX_SRCS)))
EMPTY_LINT_REPORT := $(BUILD_DIR)/.$(LINT_EXT)
NONEMPTY_LINT_REPORT := $(BUILD_DIR)/$(LINT_EXT)
# PY$(PROJECT)_SRC is the python wrapper for $(PROJECT)
PY$(PROJECT)_SRC := python/$(PROJECT)/_$(PROJECT).cpp
PY$(PROJECT)_SO := python/$(PROJECT)/_$(PROJECT).so
PY$(PROJECT)_HXX := include/$(PROJECT)/layers/python_layer.hpp
# MAT$(PROJECT)_SRC is the mex entrance point of matlab package for $(PROJECT)
MAT$(PROJECT)_SRC := matlab/+$(PROJECT)/private/$(PROJECT)_.cpp
ifneq ($(MATLAB_DIR),)
    MAT_SO_EXT := $(shell $(MATLAB_DIR)/bin/mexext)
endif
MAT$(PROJECT)_SO := matlab/+$(PROJECT)/private/$(PROJECT)_.$(MAT_SO_EXT)

##############################
# Derive generated files
##############################
# The generated files for protocol buffers
#生成的proto的.pb.h和.pb.cc
PROTO_GEN_HEADER_SRCS := $(addprefix $(PROTO_BUILD_DIR)/, \
        $(notdir ${PROTO_SRCS:.proto=.pb.h}))
PROTO_GEN_HEADER := $(addprefix $(PROTO_BUILD_INCLUDE_DIR)/, \
        $(notdir ${PROTO_SRCS:.proto=.pb.h}))
PROTO_GEN_CC := $(addprefix $(BUILD_DIR)/, ${PROTO_SRCS:.proto=.pb.cc})
PY_PROTO_BUILD_DIR := python/$(PROJECT)/proto
PY_PROTO_INIT := python/$(PROJECT)/proto/__init__.py
PROTO_GEN_PY := $(foreach file,${PROTO_SRCS:.proto=_pb2.py}, \
        $(PY_PROTO_BUILD_DIR)/$(notdir $(file)))
# The objects corresponding to the source files
# These objects will be linked into the final shared library, so we
# exclude the tool, example, and test objects.
CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o})
CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o})
PROTO_OBJS := ${PROTO_GEN_CC:.cc=.o}
OBJS := $(PROTO_OBJS) $(CXX_OBJS) $(CU_OBJS)
# tool, example, and test objects
TOOL_OBJS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o})
TOOL_BUILD_DIR := $(BUILD_DIR)/tools
TEST_CXX_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT)/test
TEST_CU_BUILD_DIR := $(BUILD_DIR)/cuda/src/$(PROJECT)/test
TEST_CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o})
TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o})
TEST_OBJS := $(TEST_CXX_OBJS) $(TEST_CU_OBJS)
GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o})
EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o})
# Output files for automatic dependency generation
DEPS := ${CXX_OBJS:.o=.d} ${CU_OBJS:.o=.d} ${TEST_CXX_OBJS:.o=.d} \
    ${TEST_CU_OBJS:.o=.d} $(BUILD_DIR)/${MAT$(PROJECT)_SO:.$(MAT_SO_EXT)=.d}
# tool, example, and test bins
TOOL_BINS := ${TOOL_OBJS:.o=.bin}
EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin}
# symlinks to tool bins without the &quot;.bin&quot; extension
TOOL_BIN_LINKS := ${TOOL_BINS:.bin=}
# Put the test binaries in build/test for convenience.
TEST_BIN_DIR := $(BUILD_DIR)/test
TEST_CU_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \
        $(foreach obj,$(TEST_CU_OBJS),$(basename $(notdir $(obj))))))
TEST_CXX_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \
        $(foreach obj,$(TEST_CXX_OBJS),$(basename $(notdir $(obj))))))
TEST_BINS := $(TEST_CXX_BINS) $(TEST_CU_BINS)
# TEST_ALL_BIN is the test binary that links caffe dynamically.
TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin

##############################
# Derive compiler warning dump locations
# 告警信息的路径
##############################
WARNS_EXT := warnings.txt
CXX_WARNS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o.$(WARNS_EXT)})
CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o.$(WARNS_EXT)})
TOOL_WARNS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o.$(WARNS_EXT)})
EXAMPLE_WARNS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o.$(WARNS_EXT)})
TEST_WARNS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o.$(WARNS_EXT)})
TEST_CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o.$(WARNS_EXT)})
ALL_CXX_WARNS := $(CXX_WARNS) $(TOOL_WARNS) $(EXAMPLE_WARNS) $(TEST_WARNS)
ALL_CU_WARNS := $(CU_WARNS) $(TEST_CU_WARNS)
ALL_WARNS := $(ALL_CXX_WARNS) $(ALL_CU_WARNS)

EMPTY_WARN_REPORT := $(BUILD_DIR)/.$(WARNS_EXT)
NONEMPTY_WARN_REPORT := $(BUILD_DIR)/$(WARNS_EXT)

##############################
# Derive include and lib directories
##############################
CUDA_INCLUDE_DIR := $(CUDA_DIR)/include

CUDA_LIB_DIR :=
# add &lt;cuda&gt;/lib64 only if it exists
ifneq (&quot;$(wildcard $(CUDA_DIR)/lib64)&quot;,&quot;&quot;)
    CUDA_LIB_DIR += $(CUDA_DIR)/lib64
endif
CUDA_LIB_DIR += $(CUDA_DIR)/lib

INCLUDE_DIRS += $(BUILD_INCLUDE_DIR) ./src ./include
ifneq ($(CPU_ONLY), 1)
    INCLUDE_DIRS += $(CUDA_INCLUDE_DIR)
    LIBRARY_DIRS += $(CUDA_LIB_DIR)
    LIBRARIES := cudart cublas curand
endif

LIBRARIES += glog gflags protobuf boost_system boost_filesystem m

# handle IO dependencies
USE_LEVELDB ?= 1 #?=表示，如果变量没有被定义过，那么就等于后者，如果定义过，则什么也不做
USE_LMDB ?= 1
# This code is taken from https://github.com/sh1r0/caffe-android-lib
USE_HDF5 ?= 1
USE_OPENCV ?= 1

ifeq ($(USE_LEVELDB), 1)
    LIBRARIES += leveldb snappy
endif
ifeq ($(USE_LMDB), 1)
    LIBRARIES += lmdb
endif
# This code is taken from https://github.com/sh1r0/caffe-android-lib
ifeq ($(USE_HDF5), 1)
    LIBRARIES += hdf5_hl hdf5
endif
ifeq ($(USE_OPENCV), 1)
    LIBRARIES += opencv_core opencv_highgui opencv_imgproc

    ifeq ($(OPENCV_VERSION), 3)
        LIBRARIES += opencv_imgcodecs
    endif

endif
PYTHON_LIBRARIES ?= boost_python python2.7
WARNINGS := -Wall -Wno-sign-compare

##############################
# Set build directories
# 设置构建的路径
##############################

DISTRIBUTE_DIR ?= distribute
DISTRIBUTE_SUBDIRS := $(DISTRIBUTE_DIR)/bin $(DISTRIBUTE_DIR)/lib
DIST_ALIASES := dist
ifneq ($(strip $(DISTRIBUTE_DIR)),distribute)
        DIST_ALIASES += distribute
endif

ALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \
    $(addprefix $(BUILD_DIR)/cuda/, $(SRC_DIRS)) \
    $(LIB_BUILD_DIR) $(TEST_BIN_DIR) $(PY_PROTO_BUILD_DIR) $(LINT_OUTPUT_DIR) \
    $(DISTRIBUTE_SUBDIRS) $(PROTO_BUILD_INCLUDE_DIR))

##############################
# Set directory for Doxygen-generated documentation
##############################
DOXYGEN_CONFIG_FILE ?= ./.Doxyfile
# should be the same as OUTPUT_DIRECTORY in the .Doxyfile
DOXYGEN_OUTPUT_DIR ?= ./doxygen
DOXYGEN_COMMAND ?= doxygen
# All the files that might have Doxygen documentation.
DOXYGEN_SOURCES := $(shell find \
    src/$(PROJECT) \
    include/$(PROJECT) \
    python/ \
    matlab/ \
    examples \
    tools \
    -name &quot;*.cpp&quot; -or -name &quot;*.hpp&quot; -or -name &quot;*.cu&quot; -or -name &quot;*.cuh&quot; -or \
        -name &quot;*.py&quot; -or -name &quot;*.m&quot;)
DOXYGEN_SOURCES += $(DOXYGEN_CONFIG_FILE)


##############################
# Configure build
##############################

# Determine platform 判断构建的平台，支持Linux、os x、，判断好之后设置编译器，还有boost
UNAME := $(shell uname -s)
ifeq ($(UNAME), Linux)
    LINUX := 1
else ifeq ($(UNAME), Darwin)
    OSX := 1
    OSX_MAJOR_VERSION := $(shell sw_vers -productVersion | cut -f 1 -d .)
    OSX_MINOR_VERSION := $(shell sw_vers -productVersion | cut -f 2 -d .)
endif

# Linux
ifeq ($(LINUX), 1)
    CXX ?= /usr/bin/g++
    GCCVERSION := $(shell $(CXX) -dumpversion | cut -f1,2 -d.)
    # older versions of gcc are too dumb to build boost with -Wuninitalized
    ifeq ($(shell echo | awk &#39;{exit $(GCCVERSION) &lt; 4.6;}&#39;), 1)
        WARNINGS += -Wno-uninitialized
    endif
    # boost::thread is reasonably called boost_thread (compare OS X)
    # We will also explicitly add stdc++ to the link target.
    LIBRARIES += boost_thread stdc++
    VERSIONFLAGS += -Wl,-soname,$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../lib
endif

# OS X:
# clang++ instead of g++
# libstdc++ for NVCC compatibility on OS X &gt;= 10.9 with CUDA &lt; 7.0
ifeq ($(OSX), 1)
    CXX := /usr/bin/clang++
    ifneq ($(CPU_ONLY), 1)
        CUDA_VERSION := $(shell $(CUDA_DIR)/bin/nvcc -V | grep -o &#39;release [0-9.]*&#39; | tr -d &#39;[a-z ]&#39;)
        ifeq ($(shell echo | awk &#39;{exit $(CUDA_VERSION) &lt; 7.0;}&#39;), 1)
            CXXFLAGS += -stdlib=libstdc++
            LINKFLAGS += -stdlib=libstdc++
        endif
        # clang throws this warning for cuda headers
        WARNINGS += -Wno-unneeded-internal-declaration
        # 10.11 strips DYLD_* env vars so link CUDA (rpath is available on 10.5+)
        OSX_10_OR_LATER   := $(shell [ $(OSX_MAJOR_VERSION) -ge 10 ] &amp;&amp; echo true)
        OSX_10_5_OR_LATER := $(shell [ $(OSX_MINOR_VERSION) -ge 5 ] &amp;&amp; echo true)
        ifeq ($(OSX_10_OR_LATER),true)
            ifeq ($(OSX_10_5_OR_LATER),true)
                LDFLAGS += -Wl,-rpath,$(CUDA_LIB_DIR)
            endif
        endif
    endif
    # gtest needs to use its own tuple to not conflict with clang
    COMMON_FLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1
    # boost::thread is called boost_thread-mt to mark multithreading on OS X
    LIBRARIES += boost_thread-mt
    # we need to explicitly ask for the rpath to be obeyed
    ORIGIN := @loader_path
    VERSIONFLAGS += -Wl,-install_name,@rpath/$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../../build/lib
else
    ORIGIN := \$$ORIGIN
endif

# Custom compiler，自定义编译器
ifdef CUSTOM_CXX
    CXX := $(CUSTOM_CXX)
endif

# Static linking 静态链接
ifneq (,$(findstring clang++,$(CXX)))
    STATIC_LINK_COMMAND := -Wl,-force_load $(STATIC_NAME)
else ifneq (,$(findstring g++,$(CXX)))
    STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive
else
  # The following line must not be indented with a tab, since we are not inside a target
  $(error Cannot static link with the $(CXX) compiler)
endif

# Debugging 判断是否打开debug选项
ifeq ($(DEBUG), 1)
    COMMON_FLAGS += -DDEBUG -g -O0
    NVCCFLAGS += -G
else
    COMMON_FLAGS += -DNDEBUG -O2
endif

# cuDNN acceleration configuration.cudnn加速配置是否打开
ifeq ($(USE_CUDNN), 1)
    LIBRARIES += cudnn
    COMMON_FLAGS += -DUSE_CUDNN
endif

# NCCL acceleration configuration nccl加速配置
ifeq ($(USE_NCCL), 1)
    LIBRARIES += nccl
    COMMON_FLAGS += -DUSE_NCCL
endif

# configure IO libraries
ifeq ($(USE_OPENCV), 1)
    COMMON_FLAGS += -DUSE_OPENCV
endif
ifeq ($(USE_LEVELDB), 1)
    COMMON_FLAGS += -DUSE_LEVELDB
endif
ifeq ($(USE_LMDB), 1)
    COMMON_FLAGS += -DUSE_LMDB
ifeq ($(ALLOW_LMDB_NOLOCK), 1)
    COMMON_FLAGS += -DALLOW_LMDB_NOLOCK
endif
endif
# This code is taken from https://github.com/sh1r0/caffe-android-lib
ifeq ($(USE_HDF5), 1)
    COMMON_FLAGS += -DUSE_HDF5
endif

# CPU-only configuration
ifeq ($(CPU_ONLY), 1)
    OBJS := $(PROTO_OBJS) $(CXX_OBJS)
    TEST_OBJS := $(TEST_CXX_OBJS)
    TEST_BINS := $(TEST_CXX_BINS)
    ALL_WARNS := $(ALL_CXX_WARNS)
    TEST_FILTER := --gtest_filter=&quot;-*GPU*&quot;
    COMMON_FLAGS += -DCPU_ONLY
endif

# Python layer support
ifeq ($(WITH_PYTHON_LAYER), 1)
    COMMON_FLAGS += -DWITH_PYTHON_LAYER
    LIBRARIES += $(PYTHON_LIBRARIES)
endif

# BLAS configuration (default = ATLAS) ，配置blas库
BLAS ?= atlas
ifeq ($(BLAS), mkl)
    # MKL
    LIBRARIES += mkl_rt
    COMMON_FLAGS += -DUSE_MKL
    MKLROOT ?= /opt/intel/mkl
    BLAS_INCLUDE ?= $(MKLROOT)/include
    BLAS_LIB ?= $(MKLROOT)/lib $(MKLROOT)/lib/intel64
else ifeq ($(BLAS), open)
    # OpenBLAS
    LIBRARIES += openblas
else
    # ATLAS
    ifeq ($(LINUX), 1)
        ifeq ($(BLAS), atlas)
            # Linux simply has cblas and atlas
            LIBRARIES += cblas atlas
        endif
    else ifeq ($(OSX), 1)
        # OS X packages atlas as the vecLib framework
        LIBRARIES += cblas
        # 10.10 has accelerate while 10.9 has veclib
        XCODE_CLT_VER := $(shell pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep &#39;version&#39; | sed &#39;s/[^0-9]*\([0-9]\).*/\1/&#39;)
        XCODE_CLT_GEQ_7 := $(shell [ $(XCODE_CLT_VER) -gt 6 ] &amp;&amp; echo 1)
        XCODE_CLT_GEQ_6 := $(shell [ $(XCODE_CLT_VER) -gt 5 ] &amp;&amp; echo 1)
        ifeq ($(XCODE_CLT_GEQ_7), 1)
            BLAS_INCLUDE ?= /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/$(shell ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ | sort | tail -1)/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers
        else ifeq ($(XCODE_CLT_GEQ_6), 1)
            BLAS_INCLUDE ?= /System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/
            LDFLAGS += -framework Accelerate
        else
            BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/
            LDFLAGS += -framework vecLib
        endif
    endif
endif
INCLUDE_DIRS += $(BLAS_INCLUDE)
LIBRARY_DIRS += $(BLAS_LIB)

LIBRARY_DIRS += $(LIB_BUILD_DIR)

# Automatic dependency generation (nvcc is handled separately)
CXXFLAGS += -MMD -MP

# Complete build flags.
COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir))
CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS)
NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS)
# mex may invoke an older gcc that is too liberal with -Wuninitalized
MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized
LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS)

USE_PKG_CONFIG ?= 0 #pkg-config是一个shell命令，使用--libs选项可以获取opencv的库文件，--cflags获取头文件路径
ifeq ($(USE_PKG_CONFIG), 1)
    PKG_CONFIG := $(shell pkg-config opencv --libs)
else
    PKG_CONFIG :=
endif
LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \
        $(foreach library,$(LIBRARIES),-l$(library))
PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library))

# &#39;superclean&#39; target recursively* deletes all files ending with an extension
# in $(SUPERCLEAN_EXTS) below.  This may be useful if you&#39;ve built older
# versions of Caffe that do not place all generated files in a location known
# to the &#39;clean&#39; target.
#
# &#39;supercleanlist&#39; will list the files to be deleted by make superclean.
#
# * Recursive with the exception that symbolic links are never followed, per the
# default behavior of &#39;find&#39;.
SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo

# Set the sub-targets of the &#39;everything&#39; target.
EVERYTHING_TARGETS := all py$(PROJECT) test warn lint
# Only build matcaffe as part of &quot;everything&quot; if MATLAB_DIR is specified.
ifneq ($(MATLAB_DIR),)
    EVERYTHING_TARGETS += mat$(PROJECT)
endif

##############################
# Define build targets
# 设置构建的目标
##############################
.PHONY: all lib test clean docs linecount lint lintclean tools examples $(DIST_ALIASES) \
    py mat py$(PROJECT) mat$(PROJECT) proto runtest \
    superclean supercleanlist supercleanfiles warn everything

all: lib tools examples

lib: $(STATIC_NAME) $(DYNAMIC_NAME)

everything: $(EVERYTHING_TARGETS)

linecount:
    cloc --read-lang-def=$(PROJECT).cloc \
        src/$(PROJECT) include/$(PROJECT) tools examples \
        python matlab

lint: $(EMPTY_LINT_REPORT)

lintclean:
    @ $(RM) -r $(LINT_OUTPUT_DIR) $(EMPTY_LINT_REPORT) $(NONEMPTY_LINT_REPORT)

docs: $(DOXYGEN_OUTPUT_DIR)
    @ cd ./docs ; ln -sfn ../$(DOXYGEN_OUTPUT_DIR)/html doxygen

$(DOXYGEN_OUTPUT_DIR): $(DOXYGEN_CONFIG_FILE) $(DOXYGEN_SOURCES)
    $(DOXYGEN_COMMAND) $(DOXYGEN_CONFIG_FILE)

$(EMPTY_LINT_REPORT): $(LINT_OUTPUTS) | $(BUILD_DIR)
    @ cat $(LINT_OUTPUTS) &gt; $@
    @ if [ -s &quot;$@&quot; ]; then \
        cat $@; \
        mv $@ $(NONEMPTY_LINT_REPORT); \
        echo &quot;Found one or more lint errors.&quot;; \
        exit 1; \
      fi; \
      $(RM) $(NONEMPTY_LINT_REPORT); \
      echo &quot;No lint errors!&quot;;

$(LINT_OUTPUTS): $(LINT_OUTPUT_DIR)/%.lint.txt : % $(LINT_SCRIPT) | $(LINT_OUTPUT_DIR)
    @ mkdir -p $(dir $@)
    @ python $(LINT_SCRIPT) $&lt; 2&gt;&amp;1 \
        | grep -v &quot;^Done processing &quot; \
        | grep -v &quot;^Total errors found: 0&quot; \
        &gt; $@ \
        || true

test: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) $(TEST_BINS)

tools: $(TOOL_BINS) $(TOOL_BIN_LINKS)

examples: $(EXAMPLE_BINS)

py$(PROJECT): py

py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY)

#@echo会显示echo后的内容，如果没有@，则会同时显示命令本身。$@表示所有目标的挨个值，$&lt;表示
#所有依赖目标的挨个值。Q在Makefile.config中定义，Q ?= @ 可以让编译更好看，不显示Q后面的命令
$(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX) | $(DYNAMIC_NAME)
    @ echo CXX/LD -o $@ $&lt;
    $(Q)$(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \
        -o $@ $(LINKFLAGS) -l$(LIBRARY_NAME) $(PYTHON_LDFLAGS) \
        -Wl,-rpath,$(ORIGIN)/../../build/lib

mat$(PROJECT): mat

mat: $(MAT$(PROJECT)_SO)

$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME)
    @ if [ -z &quot;$(MATLAB_DIR)&quot; ]; then \
        echo &quot;MATLAB_DIR must be specified in $(CONFIG_FILE)&quot; \
            &quot;to build mat$(PROJECT).&quot;; \
        exit 1; \
    fi
    @ echo MEX $&lt;
    $(Q)$(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \
            CXX=&quot;$(CXX)&quot; \
            CXXFLAGS=&quot;\$$CXXFLAGS $(MATLAB_CXXFLAGS)&quot; \
            CXXLIBS=&quot;\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)&quot; -output $@
    @ if [ -f &quot;$(PROJECT)_.d&quot; ]; then \
        mv -f $(PROJECT)_.d $(BUILD_DIR)/${MAT$(PROJECT)_SO:.$(MAT_SO_EXT)=.d}; \
    fi

runtest: $(TEST_ALL_BIN)
    $(TOOL_BUILD_DIR)/caffe
    $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER)

pytest: py
    cd python; python -m unittest discover -s caffe/test

mattest: mat
    cd matlab; $(MATLAB_DIR)/bin/matlab -nodisplay -r &#39;caffe.run_tests(), exit()&#39;

warn: $(EMPTY_WARN_REPORT)

$(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR)
    @ cat $(ALL_WARNS) &gt; $@
    @ if [ -s &quot;$@&quot; ]; then \
        cat $@; \
        mv $@ $(NONEMPTY_WARN_REPORT); \
        echo &quot;Compiler produced one or more warnings.&quot;; \
        exit 1; \
      fi; \
      $(RM) $(NONEMPTY_WARN_REPORT); \
      echo &quot;No compiler warnings!&quot;;

$(ALL_WARNS): %.o.$(WARNS_EXT) : %.o

$(BUILD_DIR_LINK): $(BUILD_DIR)/.linked

# Create a target &quot;.linked&quot; in this BUILD_DIR to tell Make that the &quot;build&quot; link
# is currently correct, then delete the one in the OTHER_BUILD_DIR in case it
# exists and $(DEBUG) is toggled later.
$(BUILD_DIR)/.linked:
    @ mkdir -p $(BUILD_DIR)
    @ $(RM) $(OTHER_BUILD_DIR)/.linked
    @ $(RM) -r $(BUILD_DIR_LINK)
    @ ln -s $(BUILD_DIR) $(BUILD_DIR_LINK)
    @ touch $@

$(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK)
    @ mkdir -p $@

$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
    @ echo LD -o $@
    $(Q)$(CXX) -shared -o $@ $(OBJS) $(VERSIONFLAGS) $(LINKFLAGS) $(LDFLAGS)
    @ cd $(BUILD_DIR)/lib; rm -f $(DYNAMIC_NAME_SHORT);   ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT)

$(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
    @ echo AR -o $@
    $(Q)ar rcs $@ $(OBJS)

$(BUILD_DIR)/%.o: %.cpp $(PROTO_GEN_HEADER) | $(ALL_BUILD_DIRS)
    @ echo CXX $&lt;
    $(Q)$(CXX) $&lt; $(CXXFLAGS) -c -o $@ 2&gt; $@.$(WARNS_EXT) \
        || (cat $@.$(WARNS_EXT); exit 1)
    @ cat $@.$(WARNS_EXT)

$(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \
        | $(PROTO_BUILD_DIR)
    @ echo CXX $&lt;
    $(Q)$(CXX) $&lt; $(CXXFLAGS) -c -o $@ 2&gt; $@.$(WARNS_EXT) \
        || (cat $@.$(WARNS_EXT); exit 1)
    @ cat $@.$(WARNS_EXT)

$(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS)
    @ echo NVCC $&lt;
    $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $&lt; -o ${@:.o=.d} \
        -odir $(@D)
    $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $&lt; -o $@ 2&gt; $@.$(WARNS_EXT) \
        || (cat $@.$(WARNS_EXT); exit 1)
    @ cat $@.$(WARNS_EXT)

$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \
        | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
    @ echo CXX/LD -o $@ $&lt;
    $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \
        -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(LIBRARY_NAME) -Wl,-rpath,$(ORIGIN)/../lib

$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \
    $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
    @ echo LD $&lt;
    $(Q)$(CXX) $(TEST_MAIN_SRC) $&lt; $(GTEST_OBJ) \
        -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(LIBRARY_NAME) -Wl,-rpath,$(ORIGIN)/../lib

$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o \
    $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
    @ echo LD $&lt;
    $(Q)$(CXX) $(TEST_MAIN_SRC) $&lt; $(GTEST_OBJ) \
        -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(LIBRARY_NAME) -Wl,-rpath,$(ORIGIN)/../lib

# Target for extension-less symlinks to tool binaries with extension &#39;*.bin&#39;.
$(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR)
    @ $(RM) $@
    @ ln -s $(notdir $&lt;) $@

$(TOOL_BINS): %.bin : %.o | $(DYNAMIC_NAME)
    @ echo CXX/LD -o $@
    $(Q)$(CXX) $&lt; -o $@ $(LINKFLAGS) -l$(LIBRARY_NAME) $(LDFLAGS) \
        -Wl,-rpath,$(ORIGIN)/../lib

$(EXAMPLE_BINS): %.bin : %.o | $(DYNAMIC_NAME)
    @ echo CXX/LD -o $@
    $(Q)$(CXX) $&lt; -o $@ $(LINKFLAGS) -l$(LIBRARY_NAME) $(LDFLAGS) \
        -Wl,-rpath,$(ORIGIN)/../../lib

proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER)

$(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_BUILD_DIR)/%.pb.h : \
        $(PROTO_SRC_DIR)/%.proto | $(PROTO_BUILD_DIR)
    @ echo PROTOC $&lt;
    $(Q)protoc --proto_path=$(PROTO_SRC_DIR) --cpp_out=$(PROTO_BUILD_DIR) $&lt;

$(PY_PROTO_BUILD_DIR)/%_pb2.py : $(PROTO_SRC_DIR)/%.proto \
        $(PY_PROTO_INIT) | $(PY_PROTO_BUILD_DIR)
    @ echo PROTOC \(python\) $&lt;
    $(Q)protoc --proto_path=src --python_out=python $&lt;

$(PY_PROTO_INIT): | $(PY_PROTO_BUILD_DIR)
    touch $(PY_PROTO_INIT)

clean:
    @- $(RM) -rf $(ALL_BUILD_DIRS)
    @- $(RM) -rf $(OTHER_BUILD_DIR)
    @- $(RM) -rf $(BUILD_DIR_LINK)
    @- $(RM) -rf $(DISTRIBUTE_DIR)
    @- $(RM) $(PY$(PROJECT)_SO)
    @- $(RM) $(MAT$(PROJECT)_SO)

supercleanfiles:
    $(eval SUPERCLEAN_FILES := $(strip \
            $(foreach ext,$(SUPERCLEAN_EXTS), $(shell find . -name &#39;*$(ext)&#39; \
            -not -path &#39;./data/*&#39;))))

supercleanlist: supercleanfiles
    @ \
    if [ -z &quot;$(SUPERCLEAN_FILES)&quot; ]; then \
        echo &quot;No generated files found.&quot;; \
    else \
        echo $(SUPERCLEAN_FILES) | tr &#39; &#39; &#39;\n&#39;; \
    fi

superclean: clean supercleanfiles
    @ \
    if [ -z &quot;$(SUPERCLEAN_FILES)&quot; ]; then \
        echo &quot;No generated files found.&quot;; \
    else \
        echo &quot;Deleting the following generated files:&quot;; \
        echo $(SUPERCLEAN_FILES) | tr &#39; &#39; &#39;\n&#39;; \
        $(RM) $(SUPERCLEAN_FILES); \
    fi

$(DIST_ALIASES): $(DISTRIBUTE_DIR)

$(DISTRIBUTE_DIR): all py | $(DISTRIBUTE_SUBDIRS)
    # add proto
    cp -r src/caffe/proto $(DISTRIBUTE_DIR)/
    # add include
    cp -r include $(DISTRIBUTE_DIR)/
    mkdir -p $(DISTRIBUTE_DIR)/include/caffe/proto
    cp $(PROTO_GEN_HEADER_SRCS) $(DISTRIBUTE_DIR)/include/caffe/proto
    # add tool and example binaries
    cp $(TOOL_BINS) $(DISTRIBUTE_DIR)/bin
    cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin
    # add libraries
    cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib
    install -m 644 $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib
    cd $(DISTRIBUTE_DIR)/lib; rm -f $(DYNAMIC_NAME_SHORT);   ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT)
    # add python - it&#39;s not the standard way, indeed...
    cp -r python $(DISTRIBUTE_DIR)/

-include $(DEPS)

</code></pre>
<p>为什么执行make all的时候，是先开始生成protoc的文件？</p>

      
       <hr><span style="font-style: italic;color: gray;"> 转载请注明来源，欢迎对文章中的引用来源进行考证 </span>
    </div>
</article>



<div class="article_copyright">
    <p><span class="copy-title">文章标题:</span>caffe的Makefile编译体系</p>
    
    <p><span class="copy-title">本文作者:</span><a href="javascript:void(0)" target="_blank" rel="noopener" title="linqinghuang">linqinghuang</a></p>
    <p><span class="copy-title">发布时间:</span>2020-02-04, 07:51:05</p>
    <p><span class="copy-title">最后更新:</span>2020-02-05, 08:24:24</p>
    <span class="copy-title">原始链接:</span><a class="post-url" href="/2020/02/04/caffe/caffe%E7%9A%84%E7%BC%96%E8%AF%91%E4%BD%93%E7%B3%BB/" title="caffe的Makefile编译体系">http://yoursite.com/2020/02/04/caffe/caffe%E7%9A%84%E7%BC%96%E8%AF%91%E4%BD%93%E7%B3%BB/</a>
    <p>
        <span class="copy-title">版权声明:</span><i class="fa fa-creative-commons"></i> <a rel="license noopener" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" title="CC BY-NC-SA 4.0 International" target = "_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。
    </p>
</div>



    <div id="comments"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">

<script type="text/javascript">
    $.getScript('/js/gitalk.js', function () {
        var gitalk = new Gitalk({
            clientID: '',
            clientSecret: '',
            repo: 'linqinghuang.github.io',
            owner: 'linqinghuang',
            admin: ['linqinghuang'],
            id: decodeURI(location.pathname),
            distractionFreeMode: 'true',
            language: 'zh-CN',
            perPage: parseInt('10',10)
        })
        gitalk.render('comments')
    })
</script>




    




    </div>
    <div class="copyright">
        <p class="footer-entry">© linqinghuang</p>
<p class="footer-entry">Built with <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/yelog/hexo-theme-3-hexo" target="_blank">3-hexo</a> theme</p>

    </div>
    <div class="full-toc">
        <button class="full"><span class="min "></span></button>
<button class="post-toc-menu"><span class="post-toc-menu-icons"></span></button>
<div class="post-toc"><span class="post-toc-title">目录</span>
    <div class="post-toc-content">

    </div>
</div>
<a class="" id="rocket" href="javascript:void(0)" target="_blank" rel="noopener"></a>
    </div>
</div>
<div class="acParent"></div>

</body>
<script src="/js/jquery.pjax.js?v=1.0.1" ></script>

<script src="/js/script.js?v=1.0.1" ></script>
<script>
    var img_resize = 'default';
    /*作者、标签的自动补全*/
    $(function () {
        $('.search').AutoComplete({
            'data': ['#性能优化','#科学上网','#v2ray','#shadowsocks','#目标检测','#object detection','#computer vision','#gdb','#调试','#gcc','#编译','#g++','#精度测量','#mAP',],
            'itemHeight': 20,
            'width': 418
        }).AutoComplete('show');
    })
    function initArticle() {
        /*渲染对应的表格样式*/
        
            $(".post .pjax table").addClass("green_title");
        

        /*渲染打赏样式*/
        

        /*高亮代码块行号*/
        
        $('pre code').each(function(){
            var lines = $(this).text().split('\n').length - 1, widther='';
            if (lines>99) {
                widther = 'widther'
            }
            var $numbering = $('<ul/>').addClass('pre-numbering ' + widther).attr("unselectable","on");
            $(this).addClass('has-numbering ' + widther)
                    .parent()
                    .append($numbering);
            for(var i=1;i<=lines;i++){
                $numbering.append($('<li/>').text(i));
            }
        });
        

        /*访问数量*/
        
        $.getScript("//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js");
        

        /*代码高亮，行号对齐*/
        $('.pre-numbering').css('line-height',$('.has-numbering').css('line-height'));

        
    }

    /*打赏页面隐藏与展示*/
    

</script>

<!--加入行号的高亮代码块样式-->

<style>
    pre{
        position: relative;
        margin-bottom: 24px;
        border-radius: 10px;
        border: 1px solid #e2dede;
        background: #FFF;
        overflow: hidden;
    }
    code.has-numbering{
        margin-left: 30px;
    }
    code.has-numbering.widther{
        margin-left: 35px;
    }
    .pre-numbering{
        margin: 0px;
        position: absolute;
        top: 0;
        left: 0;
        width: 20px;
        padding: 0.5em 3px 0.7em 5px;
        border-right: 1px solid #C3CCD0;
        text-align: right;
        color: #AAA;
        background-color: ;
    }
    .pre-numbering.widther {
        width: 35px;
    }
</style>

<!--自定义样式设置-->
<style>
    
    
    .nav {
        width: 542px;
    }
    .nav.fullscreen {
        margin-left: -542px;
    }
    .nav-left {
        width: 120px;
    }
    
    
    @media screen and (max-width: 1468px) {
        .nav {
            width: 492px;
        }
        .nav.fullscreen {
            margin-left: -492px;
        }
        .nav-left {
            width: 100px;
        }
    }
    
    
    @media screen and (max-width: 1024px) {
        .nav {
            width: 492px;
            margin-left: -492px
        }
        .nav.fullscreen {
            margin-left: 0;
        }
        .nav .hide-list.fullscreen {
            left: 492px
        }
    }
    
    @media screen and (max-width: 426px) {
        .nav {
            width: 100%;
        }
        .nav-left {
            width: 100%;
        }
    }
    
    
    .nav-right .title-list nav a .post-title, .nav-right .title-list #local-search-result a .post-title {
        color: #383636;
    }
    
    
    .nav-right .title-list nav a .post-date, .nav-right .title-list #local-search-result a .post-date {
        color: #5e5e5f;
    }
    
    
    .nav-right nav a.hover, #local-search-result a.hover{
        background-color: #e2e0e0;
    }
    
    

    /*列表样式*/
    
    .post .pjax article .article-entry>ol, .post .pjax article .article-entry>ul, .post .pjax article>ol, .post .pjax article>ul{
        border: #e2dede solid 1px;
        border-radius: 10px;
        padding: 10px 32px 10px 56px;
    }
    .post .pjax article .article-entry li>ol, .post .pjax article .article-entry li>ul,.post .pjax article li>ol, .post .pjax article li>ul{
        padding-top: 5px;
        padding-bottom: 5px;
    }
    .post .pjax article .article-entry>ol>li, .post .pjax article .article-entry>ul>li,.post .pjax article>ol>li, .post .pjax article>ul>li{
        margin-bottom: auto;
        margin-left: auto;
    }
    .post .pjax article .article-entry li>ol>li, .post .pjax article .article-entry li>ul>li,.post .pjax article li>ol>li, .post .pjax article li>ul>li{
        margin-bottom: auto;
        margin-left: auto;
    }
    

    /* 背景图样式 */
    
    


    /*引用块样式*/
    

    /*文章列表背景图*/
    
    .nav-right:before {
        content: ' ';
        display: block;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        opacity: 0.3;
        background: url("https://i.loli.net/2019/07/22/5d3521411f3f169375.png");
        background-repeat: no-repeat;
        background-position: 50% 0;
        -ms-background-size: cover;
        -o-background-size: cover;
        -moz-background-size: cover;
        -webkit-background-size: cover;
        background-size: cover;
    }
    

    
</style>







</html>
